package com.shuqi.model.manager;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.text.TextUtils;

import com.shuqi.application.ShuqiApplication;
import com.shuqi.common.Config;
import com.shuqi.common.ConfigVersion;
import com.shuqi.common.utils.FileUtils;
import com.shuqi.common.utils.Log4an;
import com.shuqi.common.utils.Util;
import com.shuqi.database.dao.impl.TxtDownloadDao;
import com.shuqi.database.model.TxtDownload;
import com.shuqi.model.manager.FreeBookDownloadManager.DownConstant;

/**
 * 离线书籍任务类
 * 
 * @author
 * 
 */
public class TxtDownLoadManager {
    /** 线程池最大线程数量 */
    public static final int MAX_THREAD_SIZE = 3;

    /** 下载线程池 */
    private ExecutorService mThreadPool;


    private static TxtDownLoadManager mInstance;

    private List<DownStateListener> mDownStateListenerList = new ArrayList<DownStateListener>();

    private Hashtable<String, BookDownLoadTask> mDownLoadTaskMap =
            new Hashtable<String, BookDownLoadTask>();

    private TxtDownLoadManager() {
        mThreadPool = Executors.newFixedThreadPool(MAX_THREAD_SIZE);
    }

    public static synchronized TxtDownLoadManager getInstance() {
        if (mInstance == null) {
            mInstance = new TxtDownLoadManager();
        }
        return mInstance;
    }

    public void finishTask() {
        if (mDownLoadTaskMap != null) {
            for (BookDownLoadTask dlTask : mDownLoadTaskMap.values()) {
                if (dlTask != null) {
                    dlTask.setForceStopRunable(true);
                }
            }
        }
    }

    /**
     * 下载错误，接着下载
     */
    public synchronized void retryDownload(TxtDownload bookInfo) {
        if (bookInfo == null || bookInfo.getDownKey() == null
                || TextUtils.isEmpty(bookInfo.getDownloadUrl())) {
            return;
        }

        if (mDownLoadTaskMap.containsKey(bookInfo.getDownKey())) {
            return;
        }
        int download = checkDownloadState(bookInfo);
        Log4an.i("retryDownload", "isDownload(bookInfo)=" + download);
        if (download == 1) {
            notifyDownLoadState(bookInfo.getDownKey(), DownConstant.STATE_FINISH,
                    bookInfo.getFileDownloadSize(), bookInfo.getFileTotalSize(), null);
            bookInfo.setDownloadStatus(DownConstant.STATE_FINISH);
            TxtDownloadDao.getInstance().updateTxtDownloadInfo(bookInfo);
        } else if (download == 0) {
            addBookDownLoadTask(bookInfo);
        } else if (download == -1) {
            notifyDownLoadState(bookInfo.getDownKey(), DownConstant.STATE_ERROR,
                    bookInfo.getFileDownloadSize(), bookInfo.getFileTotalSize(), NO_SDCARD);
        }
    }

    private static final String DOWNLOAD_FAIL = "下载失败";
    public static final String NO_SDCARD = "SD卡不可用,请检查...";

    /**
     * 删除旧的文件
     */
    private void delOldFile(String path) {
        final File delFile = new File(path);
        try {
            if (delFile.exists()) {
                delFile.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加新的downloadTask
     * 
     * @param bookInfo
     */
    private void addBookDownLoadTask(TxtDownload bookInfo) {
        BookDownLoadTask downLoadTask = new BookDownLoadTask(bookInfo);
        mDownLoadTaskMap.put(bookInfo.getDownKey(), downLoadTask);
        downLoadTask.setStatus(DownConstant.STATE_READY);
        notifyDownLoadState(bookInfo.getDownKey(), DownConstant.STATE_READY,
                bookInfo.getFileDownloadSize(), bookInfo.getFileTotalSize(), null);
        mThreadPool.execute(downLoadTask);
    }

    /**
     * 添加下载任务,删除旧的书籍
     */
    public synchronized void downLoadBook(final TxtDownload bookInfo) {
        if (bookInfo == null || bookInfo.getDownKey() == null
                || TextUtils.isEmpty(bookInfo.getDownloadUrl())) {
            return;
        }
        String downKey = bookInfo.getDownKey();
        if (mDownLoadTaskMap.containsKey(downKey)) {
            return;
        }
        removeDownLoadBookTask(true, downKey, bookInfo.getBookId(), bookInfo.getFileName());
        bookInfo.setDownloadStatus(DownConstant.STATE_READY);
        TxtDownloadDao.getInstance().saveTxtDownloadInfo(bookInfo);
        addBookDownLoadTask(bookInfo);
    }

    /**
     * 移除下载任务
     */
    public synchronized void removeDownLoadBookTask(boolean delFile, String bookDownKey,
            String filePath, String fileName) {
        BookDownLoadTask task = mDownLoadTaskMap.remove(bookDownKey);
        if (task != null) {
            task.setStatus(DownConstant.STATE_NONE);
        }
        if (delFile) {
            try {
                Thread.sleep(200);
                File saveFile = new File(Config.BOOK_YISOU_PATH + "/" + filePath, fileName);
                if (saveFile.exists()) {
                     saveFile.delete();
//                    FileUtils.deleteDir(saveFile.getParentFile());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 
     * 注册下载状态监听
     * 
     * @param listener
     */
    public void registerDownStateListener(DownStateListener listener) {
        if (!mDownStateListenerList.contains(listener)) {
            mDownStateListenerList.add(listener);
        }
    }

    /**
     * 
     * 取消注册状态监听
     * 
     * @param listener
     */
    public void unRegisterDownStateListener(DownStateListener listener) {
        mDownStateListenerList.remove(listener);
    }

    /**
     * 检查文件是否需要下载
     * 
     * @param bookInfo
     * @return 0,未下载；1,已下载；-1,SD卡不可用
     */
    private int checkDownloadState(TxtDownload bookInfo) {
        if (!Util.isCanUseSdCard()) {
            return -1;
        }
        String downLoadPath = bookInfo.getFilePath() + "/" + bookInfo.getBookId();
        File fileDir = new File(downLoadPath);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        final File saveFile = new File(downLoadPath, bookInfo.getFileName());
        if (!saveFile.exists()) {
            try {
                saveFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        bookInfo.setFileDownloadSize(saveFile.length());
        if (bookInfo.getFileTotalSize() != 0 && saveFile.length() >= bookInfo.getFileTotalSize()) {
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * 通知更新下载状态
     * 
     * @param bid
     * @param state
     * @param loadSize
     * @param totalSize
     */
    private synchronized void notifyDownLoadState(String bid, int state, long loadSize,
            long totalSize, String msg) {
        for (DownStateListener listener : mDownStateListenerList) {
            if (listener != null) {
                listener.updateDownState(bid, state, loadSize, totalSize, msg);
            }
        }
    }

    /**
     * 下载状态监听
     * 
     * @author
     * 
     */
    public static interface DownStateListener {
        /**
         * 更新下载状态
         * 
         * @param bid
         * @param state
         * @param loadSize
         * @param totalSize
         */
        void updateDownState(String bid, int state, long loadSize, long totalSize, String msg);
    }

    /**
     * 离线书籍下载
     * 
     * @author
     * 
     */
    private class BookDownLoadTask implements Runnable {

        private TxtDownload mBookInfo;
        private boolean isForceStopRunable = false;

        public boolean isForceStopRunable() {
            return isForceStopRunable;
        }

        public void setForceStopRunable(boolean isForceStopRunable) {
            this.isForceStopRunable = isForceStopRunable;
        }

        public BookDownLoadTask(TxtDownload loadTXTInfo) {
            mBookInfo = loadTXTInfo;
        }

        public synchronized void setStatus(int status) {
            mBookInfo.setDownloadStatus(status);
        }

        public synchronized String getBookFileName() {
            if (mBookInfo != null) {
                return mBookInfo.getFileName();
            }
            return null;
        }

        @Override
        public void run() {
            downLoad();
            removeDownLoad();
        }

        private boolean isNeedDownLoad() {
            return mDownLoadTaskMap.containsKey(mBookInfo.getDownKey());
        }

        private void removeDownLoad() {
            mDownLoadTaskMap.remove(mBookInfo.getDownKey());
        }

        private void downLoad() {
            if (isNeedDownLoad()) {
                setStatus(DownConstant.STATE_DOWNLOADING);
                notifyDownLoadState(mBookInfo.getDownKey(), DownConstant.STATE_DOWNLOADING,
                        mBookInfo.getFileDownloadSize(), mBookInfo.getFileTotalSize(), null);

                Context context = ShuqiApplication.getContext();
                long downloadedSize = mBookInfo.getFileDownloadSize();
                // 修改 添加了保存路径的bookid 为了区分不同来源的书籍被覆盖
                String fileName = mBookInfo.getFilePath() + "/" + mBookInfo.getBookId();
                File saveFile = new File(fileName, mBookInfo.getFileName());
                // 下面这行代码是为了确保存储文件的路径确实存在
                File xxFile = new File(fileName);
                boolean ret = xxFile.mkdirs();
                // boolean ret = saveFile.getParentFile().mkdirs();
                RandomAccessFile downLoadFile = null;
                InputStream inPutStream = null;
                HttpGet httpGet = null;
                HttpResponse httpResponse = null;

                DefaultHttpClient httpClient = new DefaultHttpClient();

                if (Config.getNetType(context) != null
                        && ("uniwap".equals(Config.getNetType(context))
                                || "cmwap".equals(Config.getNetType(context)) || "3gwap"
                                    .equals(Config.getNetType(context)))) {
                    HttpHost proxy = new HttpHost("10.0.0.172", 80, "http");
                    httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
                }
                try {
                    httpGet = new HttpGet(mBookInfo.getDownloadUrl());
                    httpGet.setHeader("IP-SRC", "shuqi_" + Config.getNetType(context));
                    httpGet.setHeader("aak", ConfigVersion.getAppApiKey());
                    httpGet.setHeader("Accept-Encoding", "");
                    httpGet.setHeader("Range", "bytes=" + downloadedSize + "-");

                    httpResponse = httpClient.execute(httpGet);
                    long totalSize = httpResponse.getEntity().getContentLength();
                    int statusCode = httpResponse.getStatusLine().getStatusCode();
                    if (statusCode < 200 || statusCode > 300 || totalSize <= 0) {
                        throw new IOException("server error, statusCode="
                                + httpResponse.getStatusLine().getStatusCode()
                                + "---downloadedSize:" + downloadedSize + "----totalSize:"
                                + totalSize);
                    }
                    mBookInfo.setFileTotalSize(totalSize + downloadedSize);
                    inPutStream = httpResponse.getEntity().getContent();
                    byte[] buffer = new byte[2048];
                    int offset = 0;

                    downLoadFile = new RandomAccessFile(saveFile, "rwd");
                    downLoadFile.seek(downloadedSize);
                    while (mBookInfo.getFileDownloadSize() < mBookInfo.getFileTotalSize()
                            && (offset = inPutStream.read(buffer, 0, buffer.length)) != -1
                            && isNeedDownLoad()) {
                        Log4an.v("downLoad", "---downLoad---while=" + offset);
                        // 强制停止
                        if (isForceStopRunable) {
                            setStatus(DownConstant.STATE_ERROR);
                            TxtDownloadDao.getInstance().updateTxtDownloadInfo(mBookInfo);
                            notifyDownLoadState(mBookInfo.getDownKey(), DownConstant.STATE_ERROR,
                                    mBookInfo.getFileDownloadSize(), mBookInfo.getFileTotalSize(),
                                    DOWNLOAD_FAIL);
                            break;
                        }
                        downLoadFile.write(buffer, 0, offset);
                        downloadedSize += offset;

                        mBookInfo.setFileDownloadSize(downloadedSize);

                        notifyDownLoadState(mBookInfo.getDownKey(), DownConstant.STATE_DOWNLOADING,
                                mBookInfo.getFileDownloadSize(), mBookInfo.getFileTotalSize(), null);
                    }
                    if (!isNeedDownLoad() || isForceStopRunable) {
                        httpGet.abort();
                        httpClient.getConnectionManager().shutdown();
                    }

                    if (mBookInfo.getDownloadStatus() == DownConstant.STATE_DOWNLOADING
                            && isNeedDownLoad()) {
                        if (mBookInfo.getFileDownloadSize() >= mBookInfo.getFileTotalSize()) {

                            // 下载结束后，直接执行断章操作，减少进入阅读页卡顿的问题
                            // CheckTxtCatalogTool mCatalogTool = CheckTxtCatalogTool.getInstance();
                            // mCatalogTool.checkSyn(saveFile.getPath(),
                            // ShuqiApplication.getContext(), null);

                            setStatus(DownConstant.STATE_FINISH);
                            // 更新状态
                            TxtDownloadDao.getInstance().updateTxtDownloadInfo(mBookInfo);
                            notifyDownLoadState(mBookInfo.getDownKey(), DownConstant.STATE_FINISH,
                                    mBookInfo.getFileDownloadSize(), mBookInfo.getFileTotalSize(),
                                    null);
                        } else {
                            throw new RuntimeException(
                                    "下载到"
                                            + (mBookInfo.getFileDownloadSize() * 1f / mBookInfo
                                                    .getFileTotalSize()) + "中断");
                        }
                    }
                    if (mBookInfo.getDownloadStatus() == DownConstant.STATE_NONE) {
                        TxtDownloadDao.getInstance().deleteTxtDownloadInfo(mBookInfo.getBookId(),
                                mBookInfo.getDownloadUrl());
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    setStatus(DownConstant.STATE_ERROR);
                    TxtDownloadDao.getInstance().updateTxtDownloadInfo(mBookInfo);
                    notifyDownLoadState(mBookInfo.getDownKey(), DownConstant.STATE_ERROR,
                            mBookInfo.getFileDownloadSize(), mBookInfo.getFileTotalSize(), null);

                } finally {
                    try {
                        if (downLoadFile != null) {
                            downLoadFile.close();
                        }
                        if (inPutStream != null) {
                            inPutStream.close();
                        }
                    } catch (IOException e1) {
                    }
                }
            }
            if (mBookInfo.getDownloadStatus() == DownConstant.STATE_NONE) {
                TxtDownloadDao.getInstance().deleteTxtDownloadInfo(mBookInfo.getBookId(),
                        mBookInfo.getDownloadUrl());
            }
        }
    }
}
